/*
 * Copyright (c) 2025 Li Auto Inc. and its affiliates
 * Licensed under the Apache License, Version 2.0(the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* This file should never be included directly but, rather,
 * only indirectly through arch/chip/up_atomic.h
 */

#ifndef __CHIPS_SIM_INCLUDE_UP_ATOMIC_H
#define __CHIPS_SIM_INCLUDE_UP_ATOMIC_H

#ifdef __cplusplus
extern "C"
{
#endif

#include <Compiler.h>
#include <Platform_Types.h>
#include <stdatomic.h>

typedef atomic_int Atomic;

/*  \brief          原子加
 *  \param[in/out]  ptr     需要进行原子加的数据地址
 *  \param[in]      addVal  要加的数值
 *  \return         原子操作前的值
 */

static inline Atomic Os_AtomicAdd(Atomic *ptr, Atomic addVal)
{
	return atomic_fetch_add(ptr, addVal);
}

/*  \brief          原子减
 *  \param[in/out]  ptr     需要进行原子减的数据地址
 *  \param[in]      subVal  要减的数值
 *  \return         原子操作前的值
 */

static inline Atomic Os_AtomicSub(Atomic *ptr, Atomic subVal)
{
	return atomic_fetch_sub(ptr, subVal);
}

/*  \brief          原子递增
 *  \param[in/out]  ptr     需要进行原子递增的数据地址
 *  \return         原子操作前的值
 */

static inline Atomic Os_AtomicInc(Atomic *ptr)
{
	return atomic_fetch_add(ptr, 1);
}

/*  \brief          原子递减
 *  \param[in/out]  ptr     需要进行原子减的数据地址
 *  \return         原子操作前的值
 */

static inline Atomic Os_AtomicDec(Atomic *ptr)
{
	return atomic_fetch_sub(ptr, 1);
}

/*  \brief          原子或
 *  \param[in/out]  ptr     需要进行原子或的数据地址
 *  \param[in]      orVal  要或的数值
 *  \return         原子操作前的值
 */

static inline Atomic Os_AtomicOr(Atomic *ptr, Atomic orVal)
{
	return atomic_fetch_or(ptr, orVal);
}

/*  \brief          原子异或
 *  \param[in/out]  ptr     需要进行原子异或的数据地址
 *  \param[in]      xorVal  要异或的数值
 *  \return         原子操作前的值
 */

static inline Atomic Os_AtomicXor(Atomic *ptr, Atomic xorVal)
{
	return atomic_fetch_xor(ptr, xorVal);
}

/*  \brief          原子与
 *  \param[in/out]  ptr     需要进行原子与的数据地址
 *  \param[in]      andVal  要与的数值
 *  \return         原子操作前的值
 */

static inline Atomic Os_AtomicAnd(Atomic *ptr, Atomic andVal)
{
	return atomic_fetch_and(ptr, andVal);
}

/*  \brief          原子与非
 *  \param[in/out]  ptr     需要进行原子与非的数据地址
 *  \param[in]      xandVal  要与非的数值
 *  \return         原子操作前的值
 */

static inline Atomic Os_AtomicXand(Atomic *ptr, Atomic xandVal)
{
	// TODO 适配原子操作
	return *ptr;
}

/*  \brief          原子设值
 *  \param[in/out]  ptr     需要进行原子设值的数据地址
 *  \param[in]      setVal  要设值的数值
 *  \return         原子操作前的值
 */

static inline Atomic Os_AtomicSet(Atomic *ptr, Atomic setVal)
{
	return atomic_exchange(ptr, setVal);
}

/*  \brief          原子清值
 *  \param[in/out]  ptr     需要进行原子清值数据地址
 *  \return         原子操作前的值
 */

static inline Atomic Os_AtomicClean(Atomic *ptr)
{
	return atomic_exchange(ptr, 0);
}

/*  \brief          原子比较交换
 *   \details        比较*ptr与oldval的，如果两者相等，则将newval更新到*ptr并返回true,
 *                   否则返回false
 *  \param[in/out]  ptr     需要进行原子比较交换的数据地址
 *  \param[in]      oldVal  旧值
 *  \param[in]      newVal  新值
 *  \return
 *                  true(1)    比较交换成功
 *                  false(0)   比较交换失败
 */

static inline Atomic Os_AtomicCmpSwap(Atomic *ptr, Atomic oldVal, Atomic newVal)
{
	/* call strong api to avoid spurious failure. */
	return atomic_compare_exchange_strong(ptr, &oldVal, newVal);
}

#ifdef __cplusplus
}
#endif

#endif /* __CHIPS_RT_FRAMEWORK_INCLUDE_UP_ATOMIC_H */
